using System;
using System.Collections;
using System.Data;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Policy;
using PHSRAG.Utility;
using Constants=PHSRAG.Insight21.InsightUtilities.Constants;

namespace PHSRAG.Insight21.Admin
{
    /// <summary>
    /// Summary description for RefCodeManagement.
    /// </summary>
    public partial class RefCodeManagement : BasePage
    {
        #region Constants

        private const string CurrentListKey = "currentListKey_38FD02F7-34E9-4841-9841-A17D6CF142DF";
        private const string CurrentPageIndexKey = "CurrentPageIndexKey_38FD02F7-34E9-4841-9841-A17D6CF142DF";
        private const string PageCacheKey = "pageCacheKey_38FD02F7-34E9-4841-9841-A17D6CF142DF";

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private properties

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable;
                return (h == null || h[CurrentPageIndexKey] == null) ? 0 : (int) h[CurrentPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();
                h[CurrentPageIndexKey] = value;
                refCodes.CurrentPageIndex = value;
                pageCachePolicy.Cache(PageCacheKey, h);
            }
        }

        #endregion

        #region Page Events

        /// <summary>
        /// Initializes the breadcrumb.
        /// </summary>
        /// <param name="sender">Control that raised the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                breadCrumb.Add("Refcode Management",
                    Settings.GetKeyValue("SubNavigation.Admin.RefCodeManagementURL", ""),
                    Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));

                annunciator.Message = string.Empty;

                if (!Page.IsPostBack)
                {
                    LoadDomains();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Page Init
        /// </summary>
        /// <param name="e">Arguments associated with the event.</param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);

            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
        }


        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = Constants.Annunciator.Title;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }


        /// <summary>
        /// 
        /// </summary>
        private void LoadDataGrid(string refDomain, bool showBlankRow)
        {
            ArrayList refCodesList = !string.IsNullOrEmpty(refDomain) ? RefCodes.GetRefCodesByDomain(cachePolicy, refDomain) : new ArrayList();

            if (showBlankRow)
            {
                RefCode refCode = new RefCode(cachePolicy, refDomain, "", "", 'N', null);
                refCodesList.Add(refCode);
            }

            refCodes.VirtualItemCount = bottomPager.RecordCount =
                topPager.RecordCount = refCodesList.Count;

            bottomPager.PageCount = topPager.PageCount = (topPager.RecordCount/refCodes.PageSize) +
                (((topPager.RecordCount%refCodes.PageSize) == 0) ? 0 : 1);

            if (showBlankRow)
            {
                //This check is required when the total no. of records lies on the page boundary. 
                //If the number of records displayed on the last page is equal to the page size,
                //and the user clicks on Add new row, then the blank row is displayed in the next page
                CurrentPageIndex = topPager.PageCount - 1;
            }

            if (!showBlankRow && CurrentPageIndex >= topPager.PageCount)
            {
                //This check is required when the total no. of records lies on the page boundary. 
                //If the number of records displayed on the last page is equal to the page size,
                //and the user clicks on Add new row, then the blank row is displayed in the next page
                //If the user then clicks on cancel, then it should show the previous page
                CurrentPageIndex = topPager.PageCount - 1;
            }

            bottomPager.CurrentPage = topPager.CurrentPage = CurrentPageIndex + 1;

            ArrayList list = GetPageRefCodes(refCodesList,
                CurrentPageIndex*refCodes.PageSize, refCodes.PageSize);
            refCodes.DataSource = list;

            if (showBlankRow)
            {
                refCodes.EditItemIndex = list.Count - 1;
            }

            refCodes.DataBind();

            if (list.Count == 0)
            {
                gridContainer.Visible = false;
                annunciator.Message = "No refcodes to display.";
            }
            else
            {
                gridContainer.Visible = true;
                annunciator.Message = string.Empty;
                recordCount.Text = topPager.RecordCount.ToString();
            }

            ManagePagination(refCodesList.Count);
        }


        /// <summary>
        /// Populates the dropdown with values from refcodes
        /// </summary>
        private void LoadDomains()
        {
            //loading domains
            domain.Items.Clear();
            domain.Items.Add(new ListItem("--Select--", "0"));

            foreach (DataRow dr in RefCodes.GetDomains(DataAccess.ConnectionString).Rows)
            {
                string s = dr["RefDomain"].ToString();
                domain.Items.Add(new ListItem(s, s));
            }
        }


        /// <summary>
        /// Adds a blank row to the grid
        /// </summary>
        private void AddRow()
        {
            if (addNewDomain.Checked)
            {
                LoadDataGrid(null, true);
            }
            else
            {
                LoadDataGrid(domain.SelectedValue, true);
            }
        }


        /// <summary>
        /// Gets RefCode objects bound by startIndex and count that need to be shown for the page
        /// </summary>
        /// <param name="source">List of all RefCodes</param>
        /// <param name="startIndex">Starting index from where the page Refcodes start</param>
        /// <param name="count">Number of refcodes to be shown on the page</param>
        /// <returns>List of refcodes to be shown on the page</returns>
        private ArrayList GetPageRefCodes(ArrayList source, int startIndex, int count)
        {
            ArrayList pageRefCodes = new ArrayList();
            int rowCount = source.Count;

            for (int i = startIndex, end = Math.Min(i + count, rowCount); i < end; ++i)
            {
                pageRefCodes.Add(source[i]);
            }

            return pageRefCodes;
        }


        /// <summary>
        /// Sets the pager control with corresponding values(Pagination management)
        /// </summary>
        private void ManagePagination(int totalCount)
        {
            int currentPageIndex = CurrentPageIndex;
            refCodes.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*refCodes.PageSize;
            bottomPager.FirstRecord = topPager.FirstRecord = startIndex + 1;

            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(startIndex + refCodes.PageSize, totalCount);

            bottomPager.EnableFirstPage = topPager.EnableFirstPage =
                bottomPager.EnablePreviousPage = topPager.EnablePreviousPage =
                    (refCodes.CurrentPageIndex != 0);

            bottomPager.EnableLastPage = topPager.EnableLastPage =
                bottomPager.EnableNextPage = topPager.EnableNextPage =
                    (refCodes.CurrentPageIndex != (topPager.PageCount - 1));
        }

        #endregion

        #region Control Event Handlers

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                adminSubNavigation.Reset();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Displays the UI for adding new domain or modifying existing domain based on the
        /// checkbox status
        /// </summary>
        /// <param name="sender">Control that raised the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnAddNewDomainCheckedChanged(object sender, EventArgs e)
        {
            try
            {
                add.Enabled = false;
                if (addNewDomain.Checked)
                {
                    newDomain.Text = string.Empty;
                    newDomain.Visible = true;
                    domain.Visible = false;
                    gridContainer.Visible = true;
                    AddRow();
                }
                else
                {
                    newDomain.Visible = false;
                    domain.Visible = true;
                    domain.SelectedIndex = 0;
                    refCodes.EditItemIndex = -1;
                    CurrentPageIndex = 0;
                    gridContainer.Visible = false;
                    refCodes.DataSource = null;
                    refCodes.DataBind();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Adds new row to the grid
        /// </summary>
        /// <param name="sender">Control that raised the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnAddRow(object sender, EventArgs e)
        {
            try
            {
                AddRow();
                add.Enabled = false;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">Control that raised the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnRefCodesItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                {
                }

                if (e.Item.ItemType == ListItemType.EditItem)
                {
                    RefCode refCode = (RefCode) e.Item.DataItem;
                    if (refCode.Code == string.Empty)
                    {
                        e.Item.FindControl("refCodeStatic").Visible = false;
                        e.Item.FindControl("refCodeEdit").Visible = true;
                    }
                    else
                    {
                        e.Item.FindControl("refCodeStatic").Visible = true;
                        e.Item.FindControl("refCodeEdit").Visible = false;
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Loads the grid with all the corresponding refcodes
        /// </summary>
        /// <param name="sender">Control that raised the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnDomainSelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                refCodes.EditItemIndex = -1;
                CurrentPageIndex = 0;
                if (domain.SelectedIndex == 0)
                {
                    gridContainer.Visible = false;
                    add.Enabled = false;
                }
                else
                {
                    gridContainer.Visible = true;
                    LoadDataGrid(domain.SelectedValue, false);
                    add.Enabled = true;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        protected void OnRefCodesEditCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                refCodes.EditItemIndex = e.Item.ItemIndex;
                LoadDataGrid(domain.SelectedValue, false);
                add.Enabled = false;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        protected void OnRefCodesCancelCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                refCodes.EditItemIndex = -1;
                if (addNewDomain.Checked)
                {
                    addNewDomain.Checked = false;
                    newDomain.Visible = false;
                    domain.Visible = true;
                    domain.SelectedIndex = 0;
                    add.Enabled = false;
                    newDomain.Text = string.Empty;
                    refCodes.DataSource = null;
                    refCodes.DataBind();
                    gridContainer.Visible = false;
                }
                else
                {
                    LoadDataGrid(domain.SelectedValue, false);
                    add.Enabled = true;
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        protected void OnRefCodesUpdateCommand(object source, DataGridCommandEventArgs e)
        {
            try
            {
                string refcode = string.Empty;
                string refdomain;

                if (addNewDomain.Checked)
                {
                    refdomain = newDomain.Text.Trim();
                    refcode = ((TextBox) e.Item.FindControl("refCodeEdit")).Text;
                }
                else
                {
                    refdomain = domain.SelectedValue;
                    TextBox refCodeEdit = (TextBox) e.Item.FindControl("refCodeEdit");
                    if (refCodeEdit.Visible)
                    {
                        refcode = refCodeEdit.Text.Trim();
                    }
                    Label refCodeStatic = (Label) e.Item.FindControl("refCodeStatic");
                    if (refCodeStatic.Visible)
                    {
                        refcode = refCodeStatic.Text;
                    }
                }

                if (refdomain == string.Empty)
                {
                    throw new Exception("Domain cannot be empty");
                }

                if (refcode == string.Empty)
                {
                    throw new Exception("Code cannot be empty");
                }

                string refmeaning = ((TextBox) e.Item.FindControl("refMeaningEdit")).Text.Trim();

                if (refmeaning == string.Empty)
                {
                    throw new Exception("Meaning of the code cannot be empty");
                }

                char active = ((CheckBox) e.Item.FindControl("activeEdit")).Checked ? 'Y' : 'N';
                RefCode obj = new RefCode(cachePolicy, refdomain.ToUpper(), refcode.ToUpper(), refmeaning, active, null);
                obj.Save(DataAccess.ConnectionString);

                refCodes.EditItemIndex = -1;

                if (addNewDomain.Checked)
                {
                    //once a refcode with a new domain is added, change the UI to modify existing domain and set the dropdown to
                    //newly added domain

                    addNewDomain.Checked = false;
                    newDomain.Visible = false;
                    domain.Visible = true;
                    //reload the domains as a new one is added
                    LoadDomains();
                    domain.SelectedValue = newDomain.Text.ToUpper();

                    newDomain.Text = string.Empty;
                }
                LoadDataGrid(domain.SelectedValue, false);

                add.Enabled = true;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Occurs when the FirstPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the first page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnFirstPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = 0;
                refCodes.EditItemIndex = -1;
                LoadDataGrid(domain.SelectedValue, false);
                add.Enabled = true;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Occurs when the last page hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the last page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnLastPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = topPager.PageCount - 1;
                refCodes.EditItemIndex = -1;
                LoadDataGrid(domain.SelectedValue, false);
                add.Enabled = true;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Occurs when the NextPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the next page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnNextPage(object sender, CommandEventArgs e)
        {
            try
            {
                ++CurrentPageIndex;
                refCodes.EditItemIndex = -1;
                LoadDataGrid(domain.SelectedValue, false);
                add.Enabled = true;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }


        /// <summary>
        /// Occurs when the PreviousPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the previous page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnPreviousPage(object sender, CommandEventArgs e)
        {
            try
            {
                --CurrentPageIndex;
                refCodes.EditItemIndex = -1;
                LoadDataGrid(domain.SelectedValue, false);
                add.Enabled = true;
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion
    }
}